
#include "main.h"

/************************************
*  例程模式选项(0~3)
0: 按指定长度接收数据
1：按指定的包头包尾接收字节数据
2：按回车换行符结尾标识接收字符串
3：通过超时检测接收字符串
************************************/
#define     USART_DEMO_OPTION   (0)

/* 定义字符串接收相关 */
#if (USART_DEMO_OPTION == 0)
uart_data_t ur1 = {
    .rec_len = 10,  // 指定接收10个数据
};
void (*uart_receive)(uart_data_t *, uint8_t) = uart_data_receive;
void (*uart_rec_clearflag)(uart_data_t *) = uart_data_rec_clearflag;
#elif (USART_DEMO_OPTION == 1)
uart_arr_t ur1 = {
    .rec_head = {0xA5}, // 指定包头为0xA5
    .rec_head_len = 1,  // 包头长为1
    .rec_tail = {0x5A}, // 指定包尾为0x5A
    .rec_tail_len = 1,  // 包尾长为1
};
void (*uart_receive)(uart_arr_t *, uint8_t) = uart_arr_receive;
void (*uart_rec_timeout_judge)(uart_arr_t *) = uart_arr_rec_timeout_judge;
void (*uart_rec_clearflag)(uart_arr_t *) = uart_arr_rec_clearflag;
#elif (USART_DEMO_OPTION == 2)
uart_str_t ur1 = {0};
void (*uart_receive)(uart_str_t *, uint8_t) = uart_str_ln_receive;
void (*uart_rec_timeout_judge)(uart_str_t *) = uart_str_ln_rec_timeout_judge;
void (*uart_rec_clearflag)(uart_str_t *) = uart_str_ln_rec_clearflag;
#elif (USART_DEMO_OPTION == 3)
uart_str_t ur1 = {0};
void (*uart_receive)(uart_str_t *, uint8_t) = uart_str_receive;
void (*uart_rec_timeout_judge)(uart_str_t *) = uart_str_rec_timeout_judge;
void (*uart_rec_clearflag)(uart_str_t *) = uart_str_rec_clearflag;
#endif

/* 定义字符串发送数据结构体 */
uart_send_t us1 = {
    .send_head = {0x48},            // 指定包头为0x48(字符'H')
    .send_head_len = 1,             // 包头长为1
    .send_tail = {0x54},            // 指定包尾为0x54(字符'T')
    .send_tail_len = 1,             // 包尾长为1
    .send_byte = USART1_SendByte,   // 指定对应的串口发送字节函数
};

/* 初始化 */
void setup(void)
{
    // 中断分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    // 系统初始化
    USART1_Init(115200);    // USART1初始化
    TIM7_Init(1);           // TIM7初始化
    
    // 外设初始化
    HMI_Init(115200);       // 串口屏初始化
    
    // 初始化测试
    printf("********************串口及串口屏测试例程(编码为UTF-8)********************\r\n");
    printf("##串口例程现象##\r\n");
    printf("# 发送 #\r\n");
    printf("* 发送一个字节：");
    delay_ms(10); uart_send_byte(&us1, 0x41); delay_ms(10);  // 延时10ms是为了保证不和printf发送冲突，0x41 -> 'A'
    printf("\r\n");
    printf("* 发送一个数组(无校验和)：");
    delay_ms(10); uint8_t arr1[5] = {0x30, 0x31, 0x32, 0x33}; uart_send_array(&us1, arr1, 4, 0); delay_ms(10);  // 0x48 0x30 0x31 0x32 0x33 0x54 -> 'H' '0' '1' '2' '3' 'T'
    printf("\r\n");
    printf("* 发送一个数组(有校验和)：");
    delay_ms(10); uint8_t arr2[5] = {0x38, 0x39, 0x59, 0x5A}; uart_send_array(&us1, arr2, 4, 1); delay_ms(10);  // 0x48 0x38 0x39 0x59 0x5A 0x24 0x54 -> 'H' '8' '9' 'Y' 'Z' '$' 'T'
    printf("\r\n");
    printf("* 发送一个字符串：");
    delay_ms(10); uart_send_string(&us1, "USART1发送数据测试成功\r\n"); delay_ms(10);
    printf("# 接收 #\r\n");
    printf("* 注：在工程的main.c文件中修改USART_DEMO_OPTION宏可以修改接收效果\r\n");
    printf("* USART_DEMO_OPTION = 0:\r\n");
    printf("  串口会接收指定长度(默认为10)的数据并返回\r\n");
    printf("  例如(以HEX形式发送)：00 01 02 03 04 05 06 07 08 09\r\n");
    printf("* USART_DEMO_OPTION = 1:\r\n");
    printf("  串口会接收包头(默认为0xA5)包尾(默认为0x5A)之间的数据并返回\r\n");
    printf("  例如(以HEX形式发送)：A5 00 01 12 23 34 45 56 67 78 89 5A\r\n");
    printf("* USART_DEMO_OPTION = 2:\r\n");
    printf("  串口会接收回车换行符之前的数据并返回\r\n");
    printf("  例如(以文本形式发送)：Data for testing\\r\\n\r\n");
    printf("* USART_DEMO_OPTION = 3:\r\n");
    printf("  串口接收到数据就会返回，长度不超过接收的最大长度(默认为128)即可\r\n");
    printf("  例如(以文本形式发送)：Data for testing\r\n");
    printf("\r\n");
    printf("##串口屏例程现象##\r\n");
    printf("*************************************************************************\r\n");
}

/* 主循环 */
void loop(void)
{
    Uart_Process();
}

/* 串口进程 */
void Uart_Process(void)
{
    if (ur1.rec_flag)
    {
#if (USART_DEMO_OPTION == 0)
        printf("成功接收%hhu个数据：", ur1.rec_len);
        for (uint8_t i = 0; i < ur1.rec_len; i++) printf("0x%02X ", ur1.rec_data[i]);
        printf("\r\n");
#elif (USART_DEMO_OPTION == 1)
        printf("成功接收%hhu个数据：", ur1.rec_arr_len);
        for (uint8_t i = 0; i < ur1.rec_arr_len; i++) printf("0x%02X ", ur1.rec_arr[i]);
        printf("\r\n");
#elif (USART_DEMO_OPTION == 2 || USART_DEMO_OPTION == 3)
        printf("成功接收长度为%hhu的字符串：%s\r\n", ur1.rec_str_len, ur1.rec_str);
#endif
        uart_rec_clearflag(&ur1);
    }
}

/* USART1中断服务函数 */
void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE))   // 判断是否接收到数据
    {
        uart_receive(&ur1, USART_ReceiveData(USART1));
        
        USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除接收中断标志
    }
}

/* TIM7中断服务函数 */
void TIM7_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM7, TIM_IT_Update))   // 判断是否产生了定时更新中断
    {
#if (USART_DEMO_OPTION)
        uart_rec_timeout_judge(&ur1);
#endif
        
        TIM_ClearITPendingBit(TIM7, TIM_IT_Update); // 清除更新中断标志位
    }
}

/* 主函数 */
int main(void)
{
    setup();
    while (1) loop();
}
